#include "parser.h"
#include<iostream>
#include<string>
#include "parser.h"
#include "node.h"

Parser::Parser(Lexer* lexer)
    :m_lexer(lexer), currToken(nullptr){
    std::cout << "Parser Init..." << std::endl;
    currToken = lexer->scan();
}

Expr* Parser::expr() {
    Expr* x = term();
    while (currToken) {
        if (currToken->tag == '+') {
            Token* opt = currToken;
            match(((Token::TokenType)'+'));
            Expr* x1 = term();
            x = new Arith(opt, x, x1);

        }
        else if (currToken->tag == '-') {
            Token* opt = currToken;
            match(((Token::TokenType)'-'));
            Expr* x1 = term();
            x = new Arith(opt, x, x1);
        }
        else {
            move();
            break;
        }
    }
    return x;
}



Expr* Parser::term() {
    Expr* e = factor();
    while (currToken) {
        if (currToken->tag == '*') {
            Token* opt = currToken;
            match(((Token::TokenType)'*'));
            Expr* x1 = factor();
            e = new Arith(opt, e, x1);
        }
        else if (currToken->tag == '/') {
            Token* opt = currToken;
            match(((Token::TokenType)'/'));
            Expr* x1 = factor();
            e = new Arith(opt, e, x1);
        }
        else {
            return e;
        }
    }
    return e;
}

Expr* Parser::factor() {
    Expr* e;
    if (currToken->tag == 270) {
        e = new Expr();
        e->op = currToken;
        e->type = Token::NUM;
        move();
    }
    else {
        e = new Expr();
        e->op = currToken;
        e->type = Token::ID;
        move();
    }
    return e;
}

void Parser::match(Token::TokenType type) {
    if (type == currToken->tag) {
        move();
    }
}

void Parser::move() {
    currToken = m_lexer->scan();
}

Stmt* Parser::stmts() {
    if (currToken == nullptr) {
        return Stmt::null;
    }
    return new Seq(stmts(), stmt());
}

Stmt* Parser::stmt() {
    Stmt* s;
    s = assign();
    return s;
}
Assign* Parser::assign() {
    Token* idToken = currToken;
    Expr* id = new Expr();
    id->op = idToken;
    id->type = Token::ID;
    match(Token::ID);
    if (currToken->tag == '=') {
        move();
        return new Assign(id, expr());
    }
}